package changceilingcolor003;

//import toxi.color.ColorTheme;
import toxi.geom.Vec3D;


import processing.core.PApplet;


public class Person extends Actors {


	Vec3D pos;
	Actors destiny;
	int type;
	//
	Vec3D vel;//Velocity?
	float setVel;//Curen
	float maxVel;//Maximal Velocity?
	Vec3D acc;//Acceleration
	int myColor;

	Vec3D CurrentTarget;//Velocity?

	float maxForce;
	float intention;

	boolean there=false;
	float wandertheta;
	float attention_radios;
	//Vec3D distraction;///////////////////////////////////////////////////////////////
	int attention;//?
	int time_to_go_to_attraction;
	boolean distracted=false;
	int time_pass_since_last_attraction;
	int timer;
	float pHt=random1(18, 22);//person's height


	Actors ChoosenAttraction = null;

	Person(ChangCeilingColor003 _p5, Vec3D pos, Actors destiny, int type) {//basic behavior for each person-----------------------------------------------------------------------
		super(_p5,pos);
		this.pos=pos;
		this.destiny=destiny;
		ChoosenAttraction =destiny; ///////////////////////////////////////////////
		this.type=type;
		//defining the specific characters of this agent
		Type();
		//speed
		time_to_go_to_attraction =50;
		maxVel = setVel;
		vel = new Vec3D (pos.x, pos.y, pos.z);
		CurrentTarget = new Vec3D (pos.x, pos.y, pos.z);
		//distraction = new Vec3D (pos.x, pos.y, pos.z);/////////////////////////////////////////////////////
		vel.sub(destiny.GetLocation());
		vel.normalize();
		acc = new Vec3D(0, 0, 0);
		maxForce = 1;

		InterestDuration = 10;
	}
	private float random1(int i, int j) {
		// TODO Auto-generated method stub
		return 0;
	}
	public void update(World w) {///////////////////////////////////////////////////////////////////////////

		distraction(w);
		// flock(alisPeop, alisBnd);

		//checking the distance to the destiny -------------------------------------------------------
		float hDist = pos.distanceTo(destiny.GetLocation());
		if (hDist < 10) there = true;
		SetLocation(pos);
	}

	//going to a distraction point in a certain distance-------------------------------------------------------------------------------------------------------------------------------
	void distraction(World w ) 
	{
		if (time_pass_since_last_attraction>time_to_go_to_attraction )
		{          
			double MaxGrade =  0.0;
			if(p5.AllActiveActors.size() >0)
			{      
				Actors BestActorSoFar = p5.AllActiveActors.get(0);
				Actors OtherActorToCheck = p5.AllActiveActors.get(0);
				for (int i=0; i<p5.AllActiveActors.size(); i++) 
				{
					OtherActorToCheck = p5.AllActiveActors.get(i); 
					if(OtherActorToCheck == this)
					{
						continue;
					}

					double distance = GetLocation().distanceTo(OtherActorToCheck.GetLocation());

					if(distance<( attention_radios +OtherActorToCheck.GetAttractionRadious()))
					{
						double grade= GetAtrctivnessGrade(OtherActorToCheck);
						if( grade > MaxGrade)
						{
							MaxGrade = grade;
							BestActorSoFar = OtherActorToCheck;
						}
					}
				}      
				//BestActorSoFar.location.distanceTo(location) < attention_radios && 
				if (MaxGrade > 0 ) 
				{//attention_radios is the dis ------------------------------------------------------------------------------------------------------------------------
					distracted = true;          
					ChoosenAttraction =BestActorSoFar;
				}
			}
		}
		if( distracted==true && ChoosenAttraction != null) 
		{//after passing some time through the main destination/change the destination--------------------------------------------------------------------------
			CurrentTarget = ChoosenAttraction.GetLocation();
			goToDes(ChoosenAttraction.GetLocation(), intention);
			timer++;
			if (timer>ChoosenAttraction.GetIntrestDuration())
			{//the distraction time-------------------------------------------------------------
				time_pass_since_last_attraction = 0;
				timer = 0;
				distracted = false;
				goToDes(CurrentTarget, 2.0-intention);
			}
		}
		else 
		{
			time_pass_since_last_attraction++;//----------------------------------------------------------------------------
			ChoosenAttraction = destiny;
			goToDes(ChoosenAttraction.GetLocation(), intention);
		}
	}

	//v = v +||steer||*intention
	//
	void goToDes(Vec3D des, double inten) {//moving towards destination--------------------------------------------------------------------------------------------------------
		//	    println("des:(" + des.x+","+ des.y+","+ des.z+"),inten: "+inten);
		
		if(des.distanceTo(GetLocation()) > attention_radios)
			ChoosenAttraction = destiny;
		
		Vec3D ste = steer(new Vec3D(des.x, des.y, des.z));
		ste.scaleSelf((float)inten);

		vel.addSelf(ste);

		vel.limit(maxVel);  
		pos.addSelf(vel);
		acc = new Vec3D(0, 0, 0);
	}
	//Steering
	Vec3D steer(Vec3D target) {
		Vec3D steer;  // The steering vector
		Vec3D desired = target.sub(pos);
		float d = desired.magnitude();

		if (d > 0) {
			desired.normalize();
			desired.scaleSelf(maxVel);
			steer = desired.sub(vel);
			steer.limit(maxForce);
		} 
		else {
			steer = new Vec3D(0, 0, 0);
		}
		return steer;
	}

	Vec3D seek(Vec3D target) {
		Vec3D steer;  // The steering vector
		Vec3D desired = target.sub(pos);

		//    if (d > 0) {
		desired.normalize();
		desired.scaleSelf(-5000);
		steer = vel.add(desired);
		steer.limit(maxForce);
		//    } 
		//    else {
		//      steer = new Vec3D(0, 0, 0);
		//    }
		return steer;
	} 

	//wander
	void wander() {  
		float wanderR = 20;         
		float wanderD = 80;         
		float change = 0.5f;
		wandertheta += p5.random(-change, change);     
		Vec3D circleloc = vel.copy();
		circleloc.normalize();            
		circleloc.scaleSelf(wanderD);          
		circleloc.addSelf(pos);              
		Vec3D circleOffSet = new Vec3D(wanderR*PApplet.cos(wandertheta), wanderR*PApplet.sin(wandertheta), 0);
		circleOffSet.addSelf(circleloc);
		acc.addSelf(steer(circleOffSet));
	}


	Vec3D futureLoc(float dis) {
		Vec3D diff = pos.copy();
		Vec3D circleloc = vel.copy();
		circleloc.normalize();
		circleloc.scaleSelf(dis);
		diff.addSelf(circleloc);
		return diff;
	}

	//---------------------------------------------------------------
	//
	//
	//
	//
	//
	void drawPerson() {//shape of person------------------------------------------------------------------------------------------------



	}
	////Defining different characteristics for different types of agents/define once should put in the setup ----------------------------------------------------------------------------------------------------------------------------
	void Type() {



		switch (type) {
		case 1 ://visitor
			//myColor = color(193, 4, 17);
			myColor = color(150, 4, 17);
			setVel = p5.random(0.5f, 0.1f);
			intention = 1.5f;
			attention_radios = 20;
			attention = (int)p5.random(60, 1200);

			DesireList.put("ArtScent", (double)p5.Attract_to_art_1);
			DesireList.put("Type1Scent", (double)p5.Attract_to_Social_1);
			DesireList.put("Type2Scent", (double)p5.Attract_to_Dealer_1);
			DesireList.put("GoTheInitialDestinationScent", (double)p5.Go_to_Destination_1);


			SelfAttrationList.put("Type1Scent", (double)p5.SocialSent_1);
			SelfAttrationList.put("Type2Scent", (double)p5.DealerSent_1);

			break;

		case 2 :
			myColor = color(255, 255, 0);
			setVel = p5.random(0.3f, 0.2f);
			intention =0.1f;
			attention_radios =40;
			attention = (int)p5.random(500, 1000);

			DesireList.put("ArtScent", (double)p5.Attract_to_art_2);//He is an artist in exhibtion, He currently not interted in other people art
			DesireList.put("Type1Scent", (double)p5.Attract_to_Social_2);//Pay some little attention to random visitor
			DesireList.put("Type2Scent", (double)p5.Attract_to_Dealer_2);//Pay most of his attention to art collector
			DesireList.put("GoTheInitialDestinationScent", (double)p5.Go_to_Destination_2);


			SelfAttrationList.put("Type1Scent", (double)p5.SocialSent_2);
			SelfAttrationList.put("Type2Scent", (double)p5.DealerSent_2);
			break;

		case 3 :
			//myColor = color(0, 0, 255);

			myColor = color(50, 0, 255);
			setVel = p5.random(1, 0.2f);
			intention =0.5f;
			attention_radios =30;
			attention = (int)p5.random(500, 1000);

			DesireList.put("ArtScent", (double)p5.Attract_to_art_3);//He is an artist in exhibtion, He currently not interted in other people art
			DesireList.put("Type1Scent", (double)p5.Attract_to_Social_3);//Pay some little attention to random visitor
			DesireList.put("Type2Scent", (double)p5.Attract_to_Dealer_3);//Pay most of his attention to art collector
			DesireList.put("GoTheInitialDestinationScent", (double)p5.Go_to_Destination_3);

			SelfAttrationList.put("Type1Scent", (double)p5.SocialSent_3);
			SelfAttrationList.put("Type2Scent", (double)p5.DealerSent_3);
			break;


		}
	}
	private int color(int i, int j, int k) {
		return p5.color(i,j,k);
	}
	@Override
	public void Draw() {
		p5.stroke(myColor);//color control the pype------------------------------------------------------------------------------------------------------------------------
		if(p5.showDetail)
		{

			//p5.stroke(0,150, 150,80);////////draw the detail 
			p5.stroke(myColor);
			p5.ellipse(pos.x, pos.y, attention_radios, 
					attention_radios);/////////////////////////////////////////

			p5.text(time_pass_since_last_attraction+"\n"+timer, pos.x, pos.y);////////////////////////////////////////////
			p5.line(pos.x, pos.y, pos.z, CurrentTarget.x, CurrentTarget.y,CurrentTarget.z);///////////////////////////////
			// stroke(color(255, 0, 0));
			//p5.stroke(0, 255, 255);
			p5.stroke(myColor);
			//p5.stroke(255,0,0);
			p5.line(pos.x, pos.y, pos.z,ChoosenAttraction.GetLocation().x,ChoosenAttraction.GetLocation().y,ChoosenAttraction.GetLocation().z);      
		}

		p5.stroke(myColor);
		//agents head 
		p5.strokeWeight(4);


		p5.point(pos.x, pos.y, pos.z+pHt);
		//agents body
		p5.strokeWeight(1);

	}
	@Override
	double GetIntrestDuration() {


		return InterestDuration;
	}
	@Override
	public double GetAttractionRadious() {
		// TODO Auto-generated method stub
		return AttractionRadious;
	}

}
